package com.ruoyi.web.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.corundumstudio.socketio.SocketIOClient;
import com.ruoyi.common.core.domain.entity.*;
import com.ruoyi.common.enums.AlarmStatusEnum;
import com.ruoyi.common.pojo.ModelSwitchPush;
import com.ruoyi.common.utils.CoordTransformUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.SysBoatEventlogService;
import com.ruoyi.web.common.Const;
import com.ruoyi.web.common.MqttProperties;
import com.ruoyi.web.handler.MessageEventHandler;
import com.ruoyi.web.model.*;
import com.ruoyi.web.mqtt.MqttPushClient;
import com.ruoyi.web.timer.CustomScheduledTaskRegistrar;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

/**
 * DeviceService
 * 设备服务-对船通信
 *
 * @author wzzfarewell
 * @date 2019/12/6
 **/
@Slf4j
@Service
public class DeviceService implements DeviceServiceInterface {
    //模拟程序数据
    private Long id = 0L;
    private double lon = 106.233682;
    private double lat = 31.211067;
    /**
     * 云端循迹-路径
     */
    private List<SysTaskRoute> taskRoutes = new ArrayList<>();

    private final MqttProperties mqttProperties;

    private final RedisTemplate<String, String> redisTemplate;
    MqttPushClient client;

    @Resource
    SysTaskMapper sysTaskMapper;

    @Resource
    SysTaskRouteMapper sysTaskRouteMapper;

    @Resource
    SysRouteAxesMapper sysRouteAxesMapper;

    @Resource
    SysCruiseMapper sysCruiseMapper;

    @Resource
    SysBoatWaterMapper sysBoatWaterMapper;

    @Resource
    SysBoatBatteryMapper sysBoatBatteryMapper;

    @Lazy
    @Autowired
    private MessageEventHandler messageEventHandler;

    @Autowired
    public CustomScheduledTaskRegistrar customScheduledTaskRegistrar;

    @Resource
    SysBoatEventlogService sysBoatEventlogService;

    /**
     * 对船通信
     */
    private Map<String, Net2MqttJG1> net2MqttJG1Map = new HashMap<>();
    /**
     * 向船发送MQTT-云端遥控数据
     */
    Net2MqttJG1 net2MqttJG1;

    @Autowired
    public DeviceService(MqttProperties mqttProperties, RedisTemplate<String, String> redisTemplate) {
        this.mqttProperties = mqttProperties;
        this.redisTemplate = redisTemplate;
        deviceConnect();
    }

    public MqttProperties getMqttProperties() {
        return mqttProperties;
    }

    public RedisTemplate<String, String> getRedisTemplate() {
        return redisTemplate;
    }

    /**
     * 设备连接-初始化MQTT
     */
    public void deviceConnect() {
        int totalClient = 20000;
        int threadNum = 200;
        final Semaphore semaphore = new Semaphore(threadNum);
        final CountDownLatch latch = new CountDownLatch(totalClient);
        ExecutorService executorService = Executors.newCachedThreadPool();
        /*for (int i = 1; i <= totalClient; i++) {
            String deviceId = Const.DEVICE_PREFIX + i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        MqttPushClient client = new MqttPushClient(DeviceService.this, deviceId);
                        semaphore.release();
                    } catch (InterruptedException e) {
                        log.error("线程异常：{}", e.toString());
                    }
                    latch.countDown();
                }
            });
        }*/
        String deviceId = Const.DEVICE_PREFIX + System.currentTimeMillis();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    semaphore.acquire();
                    client = new MqttPushClient(DeviceService.this, deviceId);
                    semaphore.release();
                } catch (InterruptedException e) {
                    log.error("线程异常：{}", e.toString());
                }
                latch.countDown();
            }
        });
//        executorService.shutdown();
    }

    @Override
    public void publish(String topic, String data) {
        client.publish(topic, data);
//        offlineBoat(data);
    }

    /**
     * 解析接收到船的MQTT消息
     *
     * @param s
     * @param payload
     */
    @Override
    public void unPackData(String s, String payload) {
        unpackDataParm(s, payload);
    }

    /**
     * 向船发MQTT消息
     *
     * @param userId
     * @param chat
     */
    @Override
    public void parasChat(String userId, ChatBase chat) {
        if (chat != null) {
            if (chat.getModule().equalsIgnoreCase("net2MqttJG1")) { //云端遥控
                net2MqttJG1(userId, chat);
            } else if (chat.getModule().equalsIgnoreCase("net2MqttJG2")) { //云端自动-循迹
                net2MqttJG2(userId, chat);
            } else if (chat.getModule().equalsIgnoreCase("net2MqttJG3")) {
                net2MqttJG3(userId, chat);
            } else if (chat.getModule().equalsIgnoreCase("net2MqttJG4")) { //云端请求申请
                net2MqttJG4(userId, chat);
            } else if (chat.getModule().equalsIgnoreCase("HeartBeat ")) { //心跳
                heartBeat(userId, chat);
            }
        }
    }

    /**
     * 云端遥控
     *
     * @param userId
     * @param chat
     */
    @Override
    public void net2MqttJG1(String userId, ChatBase chat) {
        try {
            net2MqttJG1 = JSONObject.parseObject(chat.getContent(), Net2MqttJG1.class);
            String topic = Const.DEVICE_MQTT_JP_TOPIC;
            if (net2MqttJG1 != null) {
                net2MqttJG1.setUserId(Long.parseLong(userId));
                if (net2MqttJG1.getStatus() == 1) {
                    //开始遥控模式无人船巡河
                    startTimer(topic);
//                    startSimulationRemote(topic,net2MqttJG1);
                    //TODO 模拟申请控制
                    pushControlStatus(1);
                    //TODO 新增一条无人船巡河记录
                } else {
                    //mqtt推送急停
                    emergencyStopTask();
                    //停止遥控模式无人船巡河
                    stopTimer(topic);
//                    stopSimulationRemote(topic,net2MqttJG1);
                    //TODO 模拟申请控制
                    pushControlStatus(0);
                    //TODO 停止无人船巡河
                }
            }
        } catch (Exception e) {
            log.error("转换net2MqttJG1异常：{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 急停
     */
    public void emergencyStopTask() {
        if (net2MqttJG1 != null) {
            net2MqttJG1.setCommand_Fx(0.0f);
            net2MqttJG1.setCommand_Fy(0.0f);
            net2MqttJG1.setCommand_Mz(0.0f);
            net2MqttJG1.setThruster_PORT_rpm(0);
            net2MqttJG1.setThruster_STBD_rpm(0);
            net2MqttJG1.setThruster_PORT_ang(0);
            net2MqttJG1.setThruster_STBD_ang(0);
            pushNet2MqttJG1(Const.DEVICE_MQTT_JP_TOPIC, net2MqttJG1);
        }
    }

    /**
     * 改变船方向
     *
     * @param boatDirectionParam
     */
    public void changeBoatDirection(BoatDirectionParam boatDirectionParam) {
        if (boatDirectionParam != null && net2MqttJG1 != null) {
            net2MqttJG1.setCommand_Fx(boatDirectionParam.getCommand_Fx());
            net2MqttJG1.setCommand_Mz(boatDirectionParam.getCommand_Mz());
            net2MqttJG1.setThruster_PORT_rpm(boatDirectionParam.getThruster_PORT_rpm());
            net2MqttJG1.setThruster_STBD_rpm(boatDirectionParam.getThruster_STBD_rpm());
            net2MqttJG1.setThruster_PORT_ang(boatDirectionParam.getThruster_PORT_ang());
            net2MqttJG1.setThruster_STBD_ang(boatDirectionParam.getThruster_STBD_ang());
            pushNet2MqttJG1(Const.DEVICE_MQTT_JP_TOPIC, net2MqttJG1);
        }
    }

    /**
     * 向船发送云端遥控数据
     *
     * @param key
     * @param net2MqttJG1
     */
    private void pushNet2MqttJG1(String key, Net2MqttJG1 net2MqttJG1) {
        if (net2MqttJG1 != null) {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(net2MqttJG1.getRecv_type()).append(",")
                    .append(net2MqttJG1.getUser_Command()).append(",")
                    .append(net2MqttJG1.getCommand_mode()).append(",")
                    .append(net2MqttJG1.getCommand_Fx()).append(",")
                    .append(net2MqttJG1.getCommand_Fy()).append(",")
                    .append(net2MqttJG1.getCommand_Mz());

            String data = stringBuffer.toString();
            publish(key, data);
        }
    }

    /**
     * 模拟遥控模式-开
     *
     * @param key
     * @param net2MqttJG1
     */
    private void startSimulationRemote(String key, Net2MqttJG1 net2MqttJG1) {
        key = key + "remote";
        //先停止之前的任务
        customScheduledTaskRegistrar.removeTriggerTask(key);
        if (net2MqttJG1Map.containsKey(key)) {
            net2MqttJG1Map.remove(key);
        }
        //开始新任务
        net2MqttJG1Map.put(key, net2MqttJG1);
        /*String tempCron = "0/2 * * * * ?";
        customScheduledTaskRegistrar.addTriggerTask(
                key,
                ()->pushMqtt(key,net2MqttJG1),
                triggerContext -> new CronTrigger(tempCron).nextExecutionTime(triggerContext));*/
        String finalKey = key;
        customScheduledTaskRegistrar.addTriggerTask(
                key,
                () -> pushSimulationRemote(finalKey, net2MqttJG1),
                triggerContext -> new
                        PeriodicTrigger(Const.PERIOD_TEST, TimeUnit.MILLISECONDS).nextExecutionTime(triggerContext));
    }

    /**
     * 模拟遥控模式-关
     *
     * @param key
     * @param net2MqttJG1
     */
    public void stopSimulationRemote(String key, Net2MqttJG1 net2MqttJG1) {
        key = key + "remote";
        //先停止之前的任务
        customScheduledTaskRegistrar.removeTriggerTask(key);
        if (net2MqttJG1Map.containsKey(key)) {
            net2MqttJG1Map.remove(key);
        }
        //恢复初始化数据
        id = 0L;
        lon = 31.211067;
        lat = 106.233682;
        taskRoutes.clear();
    }

    /**
     * 模拟远程推送
     *
     * @param key
     * @param net2MqttJG1
     */
    private void pushSimulationRemote(String key, Net2MqttJG1 net2MqttJG1) {
        pushTaskInfo(key, net2MqttJG1);
//        pushBoatDeviceInfo(key,net2MqttJG1);
//        pushPackNetJP(key,net2MqttJG1);
//        pushPackNetPro1JP(key,net2MqttJG1);
//        pushPackNetAtJG(key,net2MqttJG1);
//        pushPackNetWqJG(key,net2MqttJG1);
    }

    /**
     * 模拟推送任务信息
     *
     * @param key
     * @param net2MqttJG1
     */
    private void pushTaskInfo(String key, Net2MqttJG1 net2MqttJG1) {
        lon = lon + 0.0001;
        id = id + 1;
        PushTaskInfo pushTaskInfo = new PushTaskInfo();
        //船状态
        SysBoatStatus sysBoatStatus = new SysBoatStatus();
        sysBoatStatus.setId(1);
        sysBoatStatus.setBoatSn("20210808");
        sysBoatStatus.setTaskId(1);
        sysBoatStatus.setDeviceId(1);
        sysBoatStatus.setRouteId(1);
        sysBoatStatus.setModel(1);
        sysBoatStatus.setStatus(1);
        sysBoatStatus.setLongitude(lon);
        sysBoatStatus.setLatitude(lat);
        sysBoatStatus.setHeading(180.5f);
        sysBoatStatus.setPitch(2.2f);
        sysBoatStatus.setRoll(1.1f);
        sysBoatStatus.setSpeed(2.5f);
        sysBoatStatus.setGNSS_status(2);
        sysBoatStatus.setCommand_mode(2);
        sysBoatStatus.setSignal_mode(2);
        sysBoatStatus.setCommand_mode(2);
        sysBoatStatus.setWaypoints_source(1);
        sysBoatStatus.setIs_cloud_control(1);
        sysBoatStatus.setHFRadio_RSSI(3);
        sysBoatStatus.setLFRadio_RSSI(3);
        sysBoatStatus.setPath_follow_status(2);
        sysBoatStatus.setCollision_risk_status(2);

        SysTaskRoute sysTaskRoute = new SysTaskRoute();
        sysTaskRoute.setId(id);
        sysTaskRoute.setTaskId(0L);
        sysTaskRoute.setLatitude(String.valueOf(lat));
        sysTaskRoute.setLongitude(String.valueOf(lon));
        sysTaskRoute.setSort(id.intValue());
        sysTaskRoute.setCreateTime(DateUtils.getNowDate());
        //根据船ID查询未完成的任务
        SysTask sysTask = sysTaskMapper.selectOne(Wrappers.<SysTask>lambdaQuery().eq(SysTask::getFinish, 0).eq(SysTask::getObjectId, net2MqttJG1.getBoatId()));
        if (Objects.nonNull(sysTask)) {
            sysTaskRoute.setTaskId(sysTask.getId());
            //插入任务路径
            sysTaskRouteMapper.insert(sysTaskRoute);
        }

        taskRoutes.add(sysTaskRoute);
        pushTaskInfo.setSysBoatStatus(sysBoatStatus);
        pushTaskInfo.setTaskRoutes(taskRoutes);
        sendMessage("pushTaskInfo", pushTaskInfo);
    }

    /**
     * 模拟向客户端发送船数据-socket
     *
     * @param key
     * @param net2MqttJG1
     */
    private void pushBoatDeviceInfo(String key, Net2MqttJG1 net2MqttJG1) {
        Map<String, String> jw = randomLonLat(31.211067, 31.221197, 106.233682, 106.264323);

        //任务列表
        List<SysTask> sysTaskArrayList = new ArrayList<>();
        SysTask sysTask = new SysTask();
        sysTask.setId(1L);
        sysTask.setFinish(0);
        sysTask.setName("潼南号无人船的智能巡河");
        sysTask.setUserId(net2MqttJG1.getUserId());
        sysTask.setCreateTime(new Date());
        sysTask.setState(1);
        sysTask.setType(2);

        //设备信息
        SysDeviceInfo sysDeviceInfo = new SysDeviceInfo();
        sysDeviceInfo.setId(1);
        sysDeviceInfo.setDeviceCode("20210808");
        sysDeviceInfo.setName("潼南号无人船");
        sysDeviceInfo.setDeviceTypeName("无人船");
        sysDeviceInfo.setVendorType(2);
        sysDeviceInfo.setVendorName("大连造船厂");
        sysDeviceInfo.setManager(101);
        sysDeviceInfo.setManagerName("管理员");
        sysDeviceInfo.setPhone("13898789808");
        sysDeviceInfo.setLongitude("31.221197");
        sysDeviceInfo.setLatitude("106.264323");
        sysDeviceInfo.setAddress("嘉陵江1号码头");
        sysDeviceInfo.setIp("192.168.0.123");
        sysDeviceInfo.setPort(9527);
        sysDeviceInfo.setAccount("admin");
        sysDeviceInfo.setPassword("admin");
        sysDeviceInfo.setFixed(0);
        sysDeviceInfo.setPlatform(0);
        sysDeviceInfo.setPlatformUrl("");
        sysDeviceInfo.setState(1);

        //船状态
        SysBoatStatus sysBoatStatus = new SysBoatStatus();
        sysBoatStatus.setId(1);
        sysBoatStatus.setBoatSn("20210808");
        sysBoatStatus.setTaskId(1);
        sysBoatStatus.setDeviceId(1);
        sysBoatStatus.setRouteId(1);
        sysBoatStatus.setModel(1);
        sysBoatStatus.setStatus(1);
        sysBoatStatus.setLongitude(Double.valueOf(jw.get("J")));
        sysBoatStatus.setLatitude(Double.valueOf(jw.get("W")));
        sysBoatStatus.setHeading(180.5f);
        sysBoatStatus.setPitch(2.2f);
        sysBoatStatus.setRoll(1.1f);
        sysBoatStatus.setSpeed(2.5f);
        sysBoatStatus.setGNSS_status(2);
        sysBoatStatus.setCommand_mode(2);
        sysBoatStatus.setSignal_mode(2);
        sysBoatStatus.setCommand_mode(2);
        sysBoatStatus.setWaypoints_source(1);
        sysBoatStatus.setIs_cloud_control(1);
        sysBoatStatus.setHFRadio_RSSI(3);
        sysBoatStatus.setLFRadio_RSSI(3);
        sysBoatStatus.setPath_follow_status(2);
        sysBoatStatus.setCollision_risk_status(2);

        //电池状态
        SysBoatBattery sysBoatBattery = new SysBoatBattery();
        sysBoatBattery.setId(1);
        sysBoatBattery.setBoatSn("20210808");
        sysBoatBattery.setTaskId(1);
        sysBoatBattery.setDeviceId(1);
        sysBoatBattery.setThruster_PORT(1200);
        sysBoatBattery.setAngle_STBD(-1200);
        sysBoatBattery.setAngle_PORT(180);
        sysBoatBattery.setAngle_STBD(179);
        sysBoatBattery.setStatus_PORT(0);
        sysBoatBattery.setStatus_STBD(1);
//        sysBoatBattery.setData_1(120.2f);
//        sysBoatBattery.setData_2(10.2f);
//        sysBoatBattery.setData_3(30.5f);
//        sysBoatBattery.setData_4(12.2f);
//        sysBoatBattery.setData_5("2");
//        sysBoatBattery.setData_6(10.6f);
//        sysBoatBattery.setData_7("1");
//        sysBoatBattery.setData_8(30.5f);
//        sysBoatBattery.setData_9("2");
//        sysBoatBattery.setData_10(26.5f);
//        sysBoatBattery.setData_11("1");
//        sysBoatBattery.setData_12("120.5");

        //水质数据
        SysBoatWater sysBoatWater = new SysBoatWater();
        sysBoatWater.setId(1);
        sysBoatWater.setBoatSn("20210808");
        sysBoatWater.setTaskId(1);
        sysBoatWater.setDeviceId(1);
        sysBoatWater.setTemp(29.9f);
        sysBoatWater.setElec(1200.2f);
        sysBoatWater.setPH(8.6f);
        sysBoatWater.setCOD(1333.3f);
        sysBoatWater.setD0(45.5f);
        sysBoatWater.setNH4(666.6f);
        sysBoatWater.setTS(30.5f);

        //污染物数据
        List<SysBoatPollute> sysBoatPolluteArrayList = new ArrayList<>();
        SysBoatPollute sysBoatPollute = new SysBoatPollute();
        sysBoatPollute.setId(1);
        sysBoatPollute.setBoatSn("20210808");
        sysBoatPollute.setTaskId(1);
        sysBoatPollute.setDeviceId(1);
        sysBoatPollute.setFrameID(1);
        sysBoatPollute.setTarget_id(1);
        sysBoatPollute.setTarget_time(1200.5566f);
        sysBoatPollute.setTarget_x(20.5);
        sysBoatPollute.setTarget_y(30.6);
        sysBoatPollute.setTarget_longitude(31.221197);
        sysBoatPollute.setTarget_latitude(106.264323);
        sysBoatPollute.setTarget_Ve(1.1f);
        sysBoatPollute.setTarget_Vn(2.2f);
        sysBoatPollute.setTarget_square_radius(5f);
        sysBoatPolluteArrayList.add(sysBoatPollute);

        sysDeviceInfo.setSysBoatStatus(sysBoatStatus);
        sysDeviceInfo.setSysBoatBattery(sysBoatBattery);
        sysDeviceInfo.setSysBoatWater(sysBoatWater);
        sysDeviceInfo.setSysBoatPollute(sysBoatPolluteArrayList);
        sysTask.setSysDeviceInfo(sysDeviceInfo);
        sysTaskArrayList.add(sysTask);
        sendMessage("sysTask", sysTaskArrayList);
    }

    private void pushPackNetJP(String key, Net2MqttJG1 net2MqttJG1) {
        Map<String, String> jw = randomLonLat(31.211067, 31.221197, 106.233682, 106.264323);
        Mqtt2NetJG mqtt2NetJG = new Mqtt2NetJG();
        mqtt2NetJG.setUTC(7662.15f);
        mqtt2NetJG.setLongitude(Double.valueOf(jw.get("J")));
        mqtt2NetJG.setLatitude(Double.valueOf(jw.get("W")));
        mqtt2NetJG.setHeading(180.5f);
        mqtt2NetJG.setPitch(2.2f);
        mqtt2NetJG.setRoll(1.1f);
        mqtt2NetJG.setV(2.5f);
        mqtt2NetJG.setGNSS_status(2);
        mqtt2NetJG.setCommand_mode("2");
        mqtt2NetJG.setSignal_mode("2");
        mqtt2NetJG.setCommand_mode("2");
        mqtt2NetJG.setWaypoints_source(1);
        mqtt2NetJG.setIs_cloud_control(1);
        mqtt2NetJG.setHFRadio_RSSI(3);
        mqtt2NetJG.setLFRadio_RSSI(3);
        mqtt2NetJG.setPath_follow_status(2);
        mqtt2NetJG.setCollision_risk_status(2);
        sendMessage("NetJP", mqtt2NetJG);
    }

    private void pushPackNetPro1JP(String key, Net2MqttJG1 net2MqttJG1) {
        Mqtt2NetPro1JG mqtt2NetPro1JG = new Mqtt2NetPro1JG();
        mqtt2NetPro1JG.setThruster_PORT(1200);
        mqtt2NetPro1JG.setAngle_STBD(-1200);
        mqtt2NetPro1JG.setAngle_PORT(180);
        mqtt2NetPro1JG.setAngle_STBD(179);
        mqtt2NetPro1JG.setStatus_PORT(0);
        mqtt2NetPro1JG.setStatus_STBD(1);
        mqtt2NetPro1JG.setVoltage(120.2f);
        mqtt2NetPro1JG.setCurrent(10.2f);
        mqtt2NetPro1JG.setSoc(30.5f);
        mqtt2NetPro1JG.setCell_H_Voltage(12.2f);
        mqtt2NetPro1JG.setCell_HV_ID("02");
        mqtt2NetPro1JG.setCell_L_Voltage(10.6f);
        mqtt2NetPro1JG.setCell_LV_ID("02");
        mqtt2NetPro1JG.setCell_H_Temp(30.5f);
        mqtt2NetPro1JG.setCell_HT_ID("02");
        mqtt2NetPro1JG.setCell_L_Temp(26.5f);
        mqtt2NetPro1JG.setCell_LT_ID("02");
        mqtt2NetPro1JG.setBattery_error(120.5f);
        sendMessage("NetPro1JP", mqtt2NetPro1JG);
    }

    /**
     * 模拟向客户端发送船体数据
     *
     * @param key
     * @param net2MqttJG1
     */
    public void pushPackNetAtJG(String key, Net2MqttJG1 net2MqttJG1) {
        try {
            Mqtt2NetAtJG mqtt2NetAtJG = new Mqtt2NetAtJG();
            mqtt2NetAtJG.setFrameID(25);
            mqtt2NetAtJG.setNum_used_tags(1);
            List<Mqtt2NetAtJGInfo> mqtt2NetAtJGInfoList = new ArrayList<>();
            Mqtt2NetAtJGInfo mqtt2NetAtJGInfo = new Mqtt2NetAtJGInfo();
            mqtt2NetAtJGInfo.setTarget_id("01");
//            mqtt2NetAtJGInfo.setTarget_time(1200.5566f);
            mqtt2NetAtJGInfo.setTarget_x(20.5);
            mqtt2NetAtJGInfo.setTarget_y(30.6);
            mqtt2NetAtJGInfo.setTarget_longitude(31.221197);
            mqtt2NetAtJGInfo.setTarget_latitude(106.264323);
            mqtt2NetAtJGInfo.setTarget_Ve(1.1f);
            mqtt2NetAtJGInfo.setTarget_Vn(2.2f);
            mqtt2NetAtJGInfo.setTarget_square_radius(5f);
            mqtt2NetAtJGInfoList.add(mqtt2NetAtJGInfo);
            mqtt2NetAtJG.setMqtt2NetAtJGInfoList(mqtt2NetAtJGInfoList);
            sendMessage("NetAtJG", mqtt2NetAtJG);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }

    /**
     * 模拟向客户端发送水质数据
     *
     * @param key
     * @param net2MqttJG1
     */
    public void pushPackNetWqJG(String key, Net2MqttJG1 net2MqttJG1) {
        try {
            Mqtt2NetWqJG mqtt2NetWqJG = new Mqtt2NetWqJG();
            mqtt2NetWqJG.setTemp(29.9f);
            mqtt2NetWqJG.setElec(1200.2f);
            mqtt2NetWqJG.setPH(8.6f);
            mqtt2NetWqJG.setCOD(1333.3f);
            mqtt2NetWqJG.setD0(45.5f);
            mqtt2NetWqJG.setNH4(666.6f);
            mqtt2NetWqJG.setTS(30.5f);
            sendMessage("NetWqJG", mqtt2NetWqJG);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param MinLon：最小经度 MaxLon： 最大经度
     *                    MinLat：最小纬度
     *                    MaxLat：最大纬度
     * @return @throws
     * @Description: 在矩形内随机生成经纬度
     */
    public Map<String, String> randomLonLat(double MinLon, double MaxLon, double MinLat, double MaxLat) {
        BigDecimal db = new BigDecimal(Math.random() * (MaxLon - MinLon) + MinLon);
        String lon = db.setScale(6, BigDecimal.ROUND_HALF_UP).toString();// 小数后6位
        db = new BigDecimal(Math.random() * (MaxLat - MinLat) + MinLat);
        String lat = db.setScale(6, BigDecimal.ROUND_HALF_UP).toString();
        Map<String, String> map = new HashMap<String, String>();
        map.put("J", lon);
        map.put("W", lat);
        return map;
    }

    /**
     * 向船发送MQTT数据-云端自动（循迹）
     *
     * @param userId
     * @param chat
     */
    @Override
    public void net2MqttJG2(String userId, ChatBase chat) {
        try {
            //TODO 模拟申请控制
            pushControlStatus(1);
            Net2MqttJG2 net2MqttJG2 = JSONObject.parseObject(chat.getContent(), Net2MqttJG2.class);
            String topic = Const.DEVICE_MQTT_JP_TOPIC;
            pushNet2MqttJG2(topic, net2MqttJG2);
        } catch (Exception e) {
            log.error("转换net2MqttJG2异常：{}", e);
        }
    }

    /**
     * 向船发送MQTT数据-云端自动（循迹）
     *
     * @param key
     * @param net2MqttJG2
     */
    private void pushNet2MqttJG2(String key, Net2MqttJG2 net2MqttJG2) {
        if (net2MqttJG2 != null) {
            List<Net2MqttJG2Point> lists = net2MqttJG2.getLists();
            if (lists != null && lists.size() > 0) {
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append(net2MqttJG2.getRecv_type()).append(",")
                        .append(net2MqttJG2.getUser_Command()).append(",")
                        .append(net2MqttJG2.getCommand_mode()).append(",")
                        .append(net2MqttJG2.getUserSpecifiedSpeed()).append(",")
                        .append(net2MqttJG2.getWP_ID()).append(",")
                        .append(lists.size());
                for (Net2MqttJG2Point net2MqttJG2Point : lists) {
                    //高德转gps
                    Double[] doubles = CoordTransformUtils.gcj02ToWgs84(net2MqttJG2Point.getWP_long(), net2MqttJG2Point.getWP_lat());
                    stringBuffer.append(",").append(doubles[0]);
                    stringBuffer.append(",").append(doubles[1]);
                }
//                stringBuffer.append("}");
                String data = stringBuffer.toString();
                publish(key, data);
            }
        }
    }

    /**
     * 向船发送MQTT数据-待定
     *
     * @param userId
     * @param chat
     */
    @Override
    public void net2MqttJG3(String userId, ChatBase chat) {

    }

    /**
     * 向船发送MQTT数据-云端请求申请
     *
     * @param userId
     * @param chat
     */
    @Override
    public void net2MqttJG4(String userId, ChatBase chat) {

    }

    /**
     * 向船发送MQTT数据-心跳
     *
     * @param userId
     * @param chat
     */
    @Override
    public void heartBeat(String userId, ChatBase chat) {

    }

    /**
     * 通过定时器每隔200毫秒向船发送云端遥控数据
     *
     * @param key
     */
    @Override
    public void startTimer(String key) {
        //先停止之前的任务
        customScheduledTaskRegistrar.removeTriggerTask(key);
        if (net2MqttJG1Map.containsKey(key)) {
            net2MqttJG1Map.remove(key);
        }
        //开始新任务
        net2MqttJG1Map.put(key, net2MqttJG1);
        /*String tempCron = "0/2 * * * * ?";
        customScheduledTaskRegistrar.addTriggerTask(
                key,
                ()->pushMqtt(key,net2MqttJG1),
                triggerContext -> new CronTrigger(tempCron).nextExecutionTime(triggerContext));*/
        customScheduledTaskRegistrar.addTriggerTask(
                key,
                () -> pushNet2MqttJG1(key, net2MqttJG1),
                triggerContext -> new
                        PeriodicTrigger(Const.PERIOD_JG1, TimeUnit.MILLISECONDS).nextExecutionTime(triggerContext));
    }

    /**
     * 停止云端遥控定时器
     *
     * @param key
     */
    @Override
    public void stopTimer(String key) {
        emergencyStopTask();
        customScheduledTaskRegistrar.removeTriggerTask(key);
        if (net2MqttJG1Map.containsKey(key)) {
            net2MqttJG1Map.remove(key);
        }
    }

    /**
     * 用户离线
     *
     * @param userId
     */
    @Override
    public void userDisconnect(String userId) {
        //停止心跳
        stopHeartbeat(userId, Const.DEVICE_MQTT_JP_TOPIC);
        //用户离线，断开对船控制
        if (net2MqttJG1Map != null && net2MqttJG1Map.size() > 0) {
            int userIdInt = 0;
            try {
                userIdInt = Integer.parseInt(userId);
            } catch (NumberFormatException e) {
                log.error("userDisconnect---userId:{}", userId, e);
            }
            for (String key :
                    net2MqttJG1Map.keySet()) {
                if (userIdInt == net2MqttJG1Map.get(key).getUserId()) {
                    stopTimer(key);
                }
            }
        }
    }

    /**
     * 申请控制
     *
     * @param isCloudControlAllowed
     * @param control
     */
    @Override
    public void applyControl(int isCloudControlAllowed, int control) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(4).append(",")
                .append(isCloudControlAllowed).append(",")
                .append(control);
        String data = stringBuffer.toString();
        publish(Const.DEVICE_MQTT_JP_TOPIC, data);
    }

    /**
     * 向客户端推送船的控制状态-socket
     *
     * @param isCloudControl
     */
    @Override
    public void pushControlStatus(int isCloudControl) {
        //由于目前只有一条船，所以暂时限制只有有一个经行中的巡河任务
        ControlStatus controlStatus = new ControlStatus();
        List<SysTask> sysTasks = sysTaskMapper.selectList(Wrappers.<SysTask>lambdaQuery().eq(SysTask::getFinish, 0));
        if (Objects.nonNull(sysTasks) && !sysTasks.isEmpty() && sysTasks.size() > 0) {
            controlStatus.setTaskId(sysTasks.get(0).getId().intValue());
        }
        controlStatus.setIsCloudControl(isCloudControl);
        sendMessage("controlStatus", controlStatus);
    }

    /**
     * 开始心跳定时器
     *
     * @param userId
     * @param key
     */
    @Override
    public void startHeartbeat(String userId, String key) {
        customScheduledTaskRegistrar.addTriggerTask(
                userId,
                () -> startHeartbeatImpl(userId, key),
                triggerContext -> new
                        PeriodicTrigger(Const.HEARTBEAT, TimeUnit.MILLISECONDS).nextExecutionTime(triggerContext));
    }

    /**
     * 停止心跳
     *
     * @param userId
     * @param key
     */
    @Override
    public void stopHeartbeat(String userId, String key) {
        stopHeartbeatImpl(userId, key);
    }

    @Override
    public void checkBoatOffline() {
        offlineBoat();
    }

    /**
     * 开始船心跳
     *
     * @param userId
     * @param key
     */
    public void startHeartbeatImpl(String userId, String key) {
        String topic = Const.DEVICE_MQTT_JP_TOPIC;
        String data = "10";
        publish(topic, data);
    }

    /**
     * 停止船心跳定时器
     *
     * @param userId
     * @param key
     */
    public void stopHeartbeatImpl(String userId, String key) {
        customScheduledTaskRegistrar.removeTriggerTask(userId);
    }

    /**
     * 解析收到船的MQTT数据
     *
     * @param s
     * @param payload
     */
    @Async("asynExecutor")
    public void unpackDataParm(String s, String payload) {
        try {
            if (payload.contains("ServerOffline")) {
                return;
            }
            /*if (!payload.contains("{") || !payload.contains("}")) {
                return;
            }*/
            if (payload.contains("{")) {
                payload = payload.replace("{", "");
            }
            if (payload.contains("}")) {
                payload = payload.replace("}", "");
            }
            if (s.contentEquals("mqtt2net_at_JG")) { // 障碍物数据
                unPackNetAtJG(payload);
            } else if (s.contentEquals("mqtt2net_pro1_JG")) { //船体数据Pro1
                unPackNetPro1JP(payload);
            } else if (s.contentEquals("mqtt2net_JG")) { //船体数据
                unPackNetJP(payload);
            } else if (s.contentEquals("net2mqtt_JG")) { //船的心跳
                unPackHeartBeat(payload);
            } else if (s.contentEquals("mqtt2net_wq_JG")) { //水质数据
                unPackNetWqJG(payload);
            }
        } catch (Exception e) {
            log.error("unpackDataParm---s:{}---payload:{}", s, payload, e);
        }
    }

    /**
     * 解析心跳数据
     *
     * @param payload
     */
    public void unPackHeartBeat(String payload) {
        try {
            payload = payload.trim();
            int heartBeat = 0;
            try {
                heartBeat = Integer.parseInt(payload);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
            HeartBeat heartBeat1 = new HeartBeat();
            heartBeat1.setHeartbeat(heartBeat);
            sendMessage("heartBeat", heartBeat1);
        } catch (Exception e) {
            log.error("unPackHeartBeat---payload:{}", payload, e);
        }
    }

    Mqtt2NetJG mqtt2NetJG = new Mqtt2NetJG();

    /**
     * 解析船体数据
     *
     * @param payload
     */
    public void unPackNetJP(String payload) {
        try {
            payload = payload.trim();

            String[] parArr = payload.split(",");
            for (int i = 0; i < parArr.length; i++) {
                mqtt2NetJG.setUTC(Float.parseFloat(parArr[0]));
                Double lng = Double.parseDouble(parArr[2]);
                Double lat = Double.parseDouble(parArr[1]);
                //GPS转高德
                Double[] wgs84ToGcj02 = CoordTransformUtils.wgs84ToGcj02(lng, lat);
                mqtt2NetJG.setLatitude(wgs84ToGcj02[1]);
                mqtt2NetJG.setLongitude(wgs84ToGcj02[0]);
                mqtt2NetJG.setHeading(Float.parseFloat(parArr[3]));
                mqtt2NetJG.setPitch(Float.parseFloat(parArr[4]));
                mqtt2NetJG.setRoll(Float.parseFloat(parArr[5]));
                mqtt2NetJG.setV(Float.parseFloat(parArr[6]));
                mqtt2NetJG.setGNSS_status(Integer.parseInt(parArr[7]));
                mqtt2NetJG.setCommand_mode(String.valueOf(parArr[8]));
                mqtt2NetJG.setSignal_mode(String.valueOf(parArr[9]));
                mqtt2NetJG.setConnection_status(Integer.parseInt(parArr[10]));
                mqtt2NetJG.setWaypoints_source(Integer.parseInt(parArr[11]));
                mqtt2NetJG.setIs_cloud_control(Integer.parseInt(parArr[12]));
                mqtt2NetJG.setHFRadio_RSSI(Integer.parseInt(parArr[13]));
                mqtt2NetJG.setLFRadio_RSSI(Integer.parseInt(parArr[14]));
                mqtt2NetJG.setCloud_RSSI(Integer.parseInt(parArr[15]));
                mqtt2NetJG.setIndex_finished_WP(Short.parseShort(parArr[16]));
                mqtt2NetJG.setWP_AutoGNC_RX_status(Integer.parseInt(parArr[17]));
                mqtt2NetJG.setIndex_finished_SK(Short.parseShort(parArr[18]));
                mqtt2NetJG.setSK_AutoGNC_RX_status(Integer.parseInt(parArr[19]));
                if (StringUtils.isNotEmpty(parArr[20])) {
                    mqtt2NetJG.setPath_follow_status(Integer.parseInt(parArr[20]));
                }
                if (StringUtils.isNotEmpty(parArr[21])) {
                    mqtt2NetJG.setCollision_risk_status(Integer.parseInt(parArr[21]));
                }
            }
            if (!StrUtil.equals(String.valueOf(parArr[7]), "00")) {
                //TODO 更新正在执行巡河的船的状态信息sys_boat_status表
                updateTask(mqtt2NetJG);
                if (sysTask != null && this.mqtt2NetJG != null) {
                    this.mqtt2NetJG.setTaskId(sysTask.getId().intValue());
                    this.mqtt2NetJG.setCruiseId(sysTask.getObjectId());
                }
                sendMessage("NetJP", mqtt2NetJG);
            }

            if (Integer.parseInt(parArr[15]) == 0) {
                AlarmStatus alarmStatus = new AlarmStatus();
                alarmStatus.setAlarmType(AlarmStatusEnum.NO_SIGNAL.getType());
                alarmStatus.setAlarmContent(AlarmStatusEnum.NO_SIGNAL.getRefer());
                sendMessage(Const.ALARM_STATUS, alarmStatus);
            }

            if (Integer.parseInt(parArr[7]) == 0) {
                AlarmStatus alarmStatus = new AlarmStatus();
                alarmStatus.setAlarmType(AlarmStatusEnum.NO_GPS.getType());
                alarmStatus.setAlarmContent(AlarmStatusEnum.NO_GPS.getRefer());
                sendMessage(Const.ALARM_STATUS, alarmStatus);
            }
        } catch (NumberFormatException e) {
            log.error("unPackNetJP---payload:{}", payload, e);
        }
    }

    public SysTask getSysTask() {
        return sysTask;
    }

    public void setSysTask(SysTask sysTask) {
        this.sysTask = sysTask;
    }

    /**
     * 更新当前进行的任务
     */
    SysTask sysTask;
    long dateStart = 0;

    private void updateTask(Mqtt2NetJG mqtt2NetJG) {
        /*if (sysTask == null && mqtt2NetJG != null) {
            List<SysTask> sysTasks = sysTaskMapper.selectList(Wrappers.<SysTask>lambdaQuery().eq(SysTask::getFinish, 0));
            if(Objects.nonNull(sysTasks) && !sysTasks.isEmpty() && sysTasks.size() > 0){
                sysTask = sysTasks.get(0);
                Date updateTime = sysTask.getUpdateTime();
                //如果更新时间为空，则更新数据
                if (updateTime == null) {
                    updateTaskDate(mqtt2NetJG);
                } else {
                    //判断更新时间是否大于10秒
                    long dateStart = updateTime.getTime();
                    long temp = (System.currentTimeMillis() - dateStart) / 1000;
                    if (temp > 10) {
                        updateTaskDate(mqtt2NetJG);
                        sysTask = null;
                    }
                }
            }
        }*/
        //如果更新时间为空，则更新数据，否则每隔10秒更新一次数据
        long temp = (System.currentTimeMillis() - dateStart) / 1000L;
        if (temp > 10) {
            dateStart = System.currentTimeMillis();
            updateTaskDate(mqtt2NetJG);
//                sysTask = null;
        }
    }

    /**
     * 更新任务数据
     *
     * @param mqtt2NetJG
     */
    private void updateTaskDate(Mqtt2NetJG mqtt2NetJG) {
        if (sysTask == null && mqtt2NetJG != null) {
            List<SysTask> sysTasks = sysTaskMapper.selectList(Wrappers.<SysTask>lambdaQuery().eq(SysTask::getFinish, 0));
            if (Objects.nonNull(sysTasks) && !sysTasks.isEmpty() && sysTasks.size() > 0) {
                sysTask = sysTasks.get(0);
            } else {
                return;
            }
        }
        sysTask.setUpdateTime(DateUtils.getNowDate());

        log.info("Is_cloud_control---{}, Command_mode---:{}", mqtt2NetJG.getIs_cloud_control(), mqtt2NetJG.getCommand_mode());
        if (mqtt2NetJG.getIs_cloud_control() == 0) {
            if (StrUtil.equals("0x00", mqtt2NetJG.getCommand_mode())) {
                //急停
                sysTask.setModelType(10);
                ModelSwitchPush modelSwitchPush = new ModelSwitchPush();
                modelSwitchPush.setTaskId(sysTask.getId());
                modelSwitchPush.setModelType(sysTask.getModelType());
                sendMessage("modelSwitch", modelSwitchPush);

                SysBoatEventlog sysBoatEventlog = new SysBoatEventlog();
                sysBoatEventlog.setTaskId(sysTask.getId());
                sysBoatEventlog.setCommandText("急停");
                sysBoatEventlog.setCruiseId(sysTask.getObjectId());
                sysBoatEventlog.setCreateTime(DateUtil.date());
                sysBoatEventlogService.save(sysBoatEventlog);
            } else if (StrUtil.equals("0x02", mqtt2NetJG.getCommand_mode())) {
                // 正常
                sysTask.setModelType(12);
                ModelSwitchPush modelSwitchPush = new ModelSwitchPush();
                modelSwitchPush.setTaskId(sysTask.getId());
                modelSwitchPush.setModelType(sysTask.getModelType());
                sendMessage("modelSwitch", modelSwitchPush);

                SysBoatEventlog sysBoatEventlog = new SysBoatEventlog();
                sysBoatEventlog.setTaskId(sysTask.getId());
                sysBoatEventlog.setCommandText("正常");
                sysBoatEventlog.setCruiseId(sysTask.getObjectId());
                sysBoatEventlog.setCreateTime(DateUtil.date());
                sysBoatEventlogService.save(sysBoatEventlog);
            } else if (StrUtil.equals("0x01", mqtt2NetJG.getCommand_mode())) {
                // 锁定
                sysTask.setModelType(11);
                ModelSwitchPush modelSwitchPush = new ModelSwitchPush();
                modelSwitchPush.setTaskId(sysTask.getId());
                modelSwitchPush.setModelType(sysTask.getModelType());
                sendMessage("modelSwitch", modelSwitchPush);

                SysBoatEventlog sysBoatEventlog = new SysBoatEventlog();
                sysBoatEventlog.setTaskId(sysTask.getId());
                sysBoatEventlog.setCommandText("锁定");
                sysBoatEventlog.setCruiseId(sysTask.getObjectId());
                sysBoatEventlog.setCreateTime(DateUtil.date());
                sysBoatEventlogService.save(sysBoatEventlog);
            }
        }
        //检查云端控制状态是否变化
        int isCloudControl = Objects.nonNull(sysTask.getIsCloudControl()) ? sysTask.getIsCloudControl() : 0;
        int is_cloud_control_mqtt = mqtt2NetJG.getIs_cloud_control();
        if (isCloudControl != is_cloud_control_mqtt) {
            sysTask.setIsCloudControl(is_cloud_control_mqtt);
            pushControlStatus(is_cloud_control_mqtt);
            //推送自动巡航轨迹
            /*if (sysTask.getModelType().equals(2)  && is_cloud_control_mqtt == 1) {
                ChatBase chatBase = pushTaskRouteAxes(sysRouteAxesMapper, sysTask, sysTask);
                parasChat(String.valueOf(sysTask.getUserId()),chatBase);
            }*/

        }
        if (Objects.nonNull(sysTask.getObjectId())) {
            if (Objects.nonNull(mqtt2NetJG.getLongitude()) && Objects.nonNull(mqtt2NetJG.getLatitude())) {
                SysCruise sysCruise = new SysCruise();
                sysCruise.setId(sysTask.getObjectId());
                sysCruise.setLongitude(String.valueOf(mqtt2NetJG.getLongitude()));
                sysCruise.setLatitude(String.valueOf(mqtt2NetJG.getLatitude()));
                sysCruiseMapper.updateById(sysCruise);
            }
        }
        sysTaskMapper.updateById(sysTask);
        //插入路径
        insertTaskRoute(mqtt2NetJG);
    }

    /**
     * 船上线
     */
    private void onlineBoat() {
        SysCruise sysCruise = sysCruiseMapper.selectOne(Wrappers.<SysCruise>lambdaQuery()
                .eq(SysCruise::getState, 1)
                .eq(SysCruise::getOnline, 0)
                .eq(SysCruise::getTopic, Const.DEVICE_NET_JG_TOPIC));
        if (sysCruise != null) {
            sendOnlineBoat(sysCruise, 1);
        }
    }

    /**
     * 船下线
     */
    private void offlineBoat() {
        long temp = (System.currentTimeMillis() - boatOnline) / 1000L;
        if (temp > 30) {
            SysCruise sysCruise = sysCruiseMapper.selectOne(Wrappers.<SysCruise>lambdaQuery()
                    .eq(SysCruise::getState, 1)
                    .eq(SysCruise::getOnline, 1)
                    .eq(SysCruise::getTopic, Const.DEVICE_NET_JG_TOPIC));
            if (sysCruise != null) {
                sendOnlineBoat(sysCruise, 0);

                SysBoatEventlog sysBoatEventlog = new SysBoatEventlog();
                sysBoatEventlog.setTaskId(sysTask.getId());
                sysBoatEventlog.setCommandText("断电或离线");
                sysBoatEventlog.setCruiseId(sysTask.getObjectId());
                sysBoatEventlog.setCreateTime(DateUtil.date());
                sysBoatEventlogService.save(sysBoatEventlog);

                CruiseStatus cruiseStatus = new CruiseStatus();
                cruiseStatus.setOnline(0);
                cruiseStatus.setCruiseId(sysTask.getObjectId());
                sendMessage("cruiseStatus", cruiseStatus);
            }
        }
    }

    /**
     * 发送船在线状态变更推送
     *
     * @param sysCruise
     * @param online
     */
    private void sendOnlineBoat(SysCruise sysCruise, int online) {
        sysCruise.setOnline(online);
        sysCruiseMapper.updateById(sysCruise);
        List<SysCruise> sysCruiseList = sysCruiseMapper.selectList(Wrappers.<SysCruise>lambdaQuery()
                .eq(SysCruise::getState, 1)
                .eq(SysCruise::getOnline, 1));
        OnlineBoat onlineBoat = new OnlineBoat();
        onlineBoat.setOnlineBoat(sysCruiseList == null ? 0 : sysCruiseList.size());
        sendMessage(Const.ONLINE_BOAT, onlineBoat);

        // 推送船的在线状态
        CruiseStatus cruiseStatus = new CruiseStatus();
        cruiseStatus.setOnline(online);
        cruiseStatus.setCruiseId(sysCruise.getId());
        log.info(Const.CRUISE_STATUS + ":{}", JSONObject.toJSONString(cruiseStatus));
        sendMessage(Const.CRUISE_STATUS, cruiseStatus);
        log.info(Const.CRUISE_STATUS + ":{ok}");
    }

    /**
     * 获取云端自动（循迹）类型
     *
     * @param sysRoute
     * @param sysTask2
     * @return
     */
    private int getRouteType(SysRoute sysRoute, SysTask sysTask2) {
        log.error("轨迹类型：" + sysRoute.getType());
        log.error("是否避障：" + sysTask2.getIsDodge());
        int type = 6;
        Integer sysRouteType = sysRoute.getType() == null ? 1 : sysRoute.getType();
        Integer isDodge = sysTask2.getIsDodge() == null ? 0 : sysTask2.getIsDodge();
        if (sysRouteType.equals(1)) {
            //闭环
            if (isDodge.equals(0)) {
                type = 6;
            } else {
                type = 16;
            }
        } else {
            //开环
            if (isDodge.equals(0)) {
                type = 1;
            } else {
                type = 11;
            }
        }
        return type;
    }

    /**
     * 向船发送云端遥控（循迹）MQTT数据
     *
     * @param sysRouteMapper
     * @param sysRouteAxesMapper
     * @param sysTask
     * @param sysTask2
     * @return
     */
    public ChatBase pushTaskRouteAxes(SysRouteMapper sysRouteMapper, SysRouteAxesMapper sysRouteAxesMapper, SysTask sysTask, SysTask sysTask2) {
        SysRoute sysRoute = sysRouteMapper.selectOne(Wrappers.<SysRoute>lambdaQuery().eq(SysRoute::getState, 1).eq(SysRoute::getId, sysTask.getPlanRouteId()));
        List<SysRouteAxes> sysRouteAxesList = sysRouteAxesMapper.selectList(Wrappers.<SysRouteAxes>lambdaQuery().eq(SysRouteAxes::getState, 1).eq(SysRouteAxes::getRoute, sysTask.getPlanRouteId()));
        String model = "net2MqttJG2";
        ChatBase chatBase = new ChatBase();
        Net2MqttJG2 net2MqttJG2 = new Net2MqttJG2();
        net2MqttJG2.setRecv_type(2);
        net2MqttJG2.setUser_Command(getRouteType(sysRoute, sysTask2));
        net2MqttJG2.setCommand_mode(sysTask2.getModelType());
        net2MqttJG2.setWP_ID((int) ((Math.random() * 9 + 1) * 10));
        net2MqttJG2.setUserSpecifiedSpeed(sysTask2.getUserSpecifiedSpeed());
        net2MqttJG2.setWP_num_used(sysRouteAxesList.size());
        List<Net2MqttJG2Point> lists = new ArrayList<>();
        if (Objects.nonNull(sysRouteAxesList) && !sysRouteAxesList.isEmpty() && sysRouteAxesList.size() > 0) {
            for (SysRouteAxes sysRouteAxes : sysRouteAxesList) {
                Net2MqttJG2Point net2MqttJG2Point = new Net2MqttJG2Point();
                try {
                    net2MqttJG2Point.setWP_lat(Double.parseDouble(sysRouteAxes.getLatitude()));
                    net2MqttJG2Point.setWP_long(Double.parseDouble(sysRouteAxes.getLongitude()));
                } catch (NumberFormatException e) {
                    log.error("pushTaskRouteAxes", e);
                }
                lists.add(net2MqttJG2Point);
            }
        }
        net2MqttJG2.setLists(lists);
        String content = JSONObject.toJSONString(net2MqttJG2);
        chatBase.setModule(model);
        chatBase.setContent(content);
        return chatBase;
    }

    /**
     * 向船发送污染源模式MQTT数据
     *
     * @param param
     * @return
     */
    public ChatBase pushTaskPollute(SysTaskPollute param) {
        List<SysTaskPolluteLocation> locationList = param.getLocationList();
        String model = "net2MqttJG2";
        ChatBase chatBase = new ChatBase();
        Net2MqttJG2 net2MqttJG2 = new Net2MqttJG2();
        net2MqttJG2.setRecv_type(2);
        net2MqttJG2.setUser_Command(11);
        net2MqttJG2.setCommand_mode(2);
        net2MqttJG2.setWP_ID((int) ((Math.random() * 9 + 1) * 10));
        net2MqttJG2.setUserSpecifiedSpeed(2);
        net2MqttJG2.setWP_num_used(locationList.size());
        List<Net2MqttJG2Point> lists = new ArrayList<>();
        if (Objects.nonNull(locationList) && !locationList.isEmpty() && locationList.size() > 0) {
            for (SysTaskPolluteLocation sysRouteAxes : locationList) {
                Net2MqttJG2Point net2MqttJG2Point = new Net2MqttJG2Point();
                try {
                    net2MqttJG2Point.setWP_lat(sysRouteAxes.getLatitude());
                    net2MqttJG2Point.setWP_long(sysRouteAxes.getLongitude());
                } catch (NumberFormatException e) {
                    log.error("pushTaskPollute", e);
                }
                lists.add(net2MqttJG2Point);
            }
        }
        net2MqttJG2.setLists(lists);
        String content = JSONObject.toJSONString(net2MqttJG2);
        chatBase.setModule(model);
        chatBase.setContent(content);
        return chatBase;
    }

    /**
     * 插入无人船任务轨迹
     *
     * @param mqtt2NetJG
     */
    private void insertTaskRoute(Mqtt2NetJG mqtt2NetJG) {
        SysTaskRoute sysTaskRoute = SysTaskRoute.builder()
                .taskId(sysTask.getId())
                .latitude(String.valueOf(mqtt2NetJG.getLatitude()))
                .longitude(String.valueOf(mqtt2NetJG.getLongitude()))
                .sort(1)
                .heading(mqtt2NetJG.getHeading())
                .pitch(mqtt2NetJG.getPitch())
                .roll(mqtt2NetJG.getRoll())
                .createTime(DateUtils.getNowDate())
                .build();
        sysTaskRouteMapper.insert(sysTaskRoute);
    }

    Mqtt2NetPro1JG mqtt2NetPro1JG = new Mqtt2NetPro1JG();
    long boatOnline = 0;

    /**
     * 解析船发过来的MQTT船体数据pro1
     *
     * @param payload
     */
    public void unPackNetPro1JP(String payload) {
        try {
            String[] parArr = payload.split(",");
            for (int i = 0; i < parArr.length; i++) {
                mqtt2NetPro1JG.setThruster_PORT(Integer.parseInt(parArr[0]));
                mqtt2NetPro1JG.setThruster_STBD(Integer.parseInt(parArr[1]));
                mqtt2NetPro1JG.setAngle_PORT(Float.parseFloat(parArr[2]));
                mqtt2NetPro1JG.setAngle_STBD(Float.parseFloat(parArr[3]));
                mqtt2NetPro1JG.setStatus_PORT(Integer.parseInt(parArr[4]));
                mqtt2NetPro1JG.setStatus_STBD(Integer.parseInt(parArr[5]));
                mqtt2NetPro1JG.setVoltage(Float.parseFloat(parArr[6]));
                mqtt2NetPro1JG.setCurrent(Float.parseFloat(parArr[7]));
                mqtt2NetPro1JG.setSoc(Float.parseFloat(parArr[8]));
                mqtt2NetPro1JG.setCell_H_Voltage(Float.parseFloat(parArr[9]));
                mqtt2NetPro1JG.setCell_HV_ID(parArr[10]);
                mqtt2NetPro1JG.setCell_L_Voltage(Float.parseFloat(parArr[11]));
                mqtt2NetPro1JG.setCell_LV_ID(parArr[12]);
                mqtt2NetPro1JG.setCell_H_Temp(Float.parseFloat(parArr[13]));
                mqtt2NetPro1JG.setCell_HT_ID(parArr[14]);
                mqtt2NetPro1JG.setCell_L_Temp(Float.parseFloat(parArr[15]));
                mqtt2NetPro1JG.setCell_LT_ID(parArr[16]);
                mqtt2NetPro1JG.setBattery_error(Float.parseFloat(parArr[17]));
                mqtt2NetPro1JG.setCharge_status(parArr[18]);
                mqtt2NetPro1JG.setI_resistance(parArr[19]);
                mqtt2NetPro1JG.setBattery_status(parArr[20]);
            }
            if (sysTask != null && this.mqtt2NetPro1JG != null) {
                this.mqtt2NetPro1JG.setTaskId(sysTask.getId().intValue());
                this.mqtt2NetPro1JG.setCruiseId(sysTask.getObjectId());
            }
            updateBattery();
            checkBoatOnline(mqtt2NetPro1JG);
            sendMessage("NetPro1JP", mqtt2NetPro1JG);
            //TODO 更新正在执行巡河的船的电池信息sys_boat_battery表
        } catch (NumberFormatException e) {
            log.error("unPackNetPro1JP---:{}", payload, e);
        }
    }

    Mqtt2NetWqJG mqtt2NetWqJG = new Mqtt2NetWqJG();

    /**
     * 解析船发过来的MQTT水质数据
     *
     * @param payload
     */
    public void unPackNetWqJG(String payload) {
        try {
            String[] parArr = payload.split(",");
            for (int i = 0; i < parArr.length; i++) {
                mqtt2NetWqJG.setTemp(Float.parseFloat(parArr[0]));
                mqtt2NetWqJG.setElec(Float.parseFloat(parArr[1]));
                mqtt2NetWqJG.setPH(Float.parseFloat(parArr[2]));
                mqtt2NetWqJG.setCOD(Float.parseFloat(parArr[3]));
                mqtt2NetWqJG.setD0(Float.parseFloat(parArr[4]));
                mqtt2NetWqJG.setNH4(Float.parseFloat(parArr[5]));
                mqtt2NetWqJG.setTS(Float.parseFloat(parArr[6]));
            }
            if (sysTask != null && mqtt2NetWqJG != null) {
                mqtt2NetWqJG.setTaskId(sysTask.getId().intValue());
                mqtt2NetWqJG.setCruiseId(sysTask.getObjectId());
            }
//            sendMessage("NetWqJG",mqtt2NetWqJG);
            updateWater();
            //TODO 更新正在执行巡河的船的水质信息sys_boat_water表
        } catch (NumberFormatException e) {
            log.error("unPackNetWqJG---:{}", payload, e);
        }
    }

    /**
     * 更新水质
     */
    private void updateWater() {
        long temp = (System.currentTimeMillis() - dateStart) / 1000L;
        if (temp > 0) {
            int level = 0;
            try {
                BigDecimal bigDecimal = new BigDecimal(String.valueOf(mqtt2NetWqJG.getPH()));
                double bigDecimalDouble = bigDecimal.doubleValue();
                level = (int) Math.ceil(bigDecimalDouble);
            } catch (Exception e) {
                log.error("updateWater---:{}", mqtt2NetWqJG.getPH(), e);
            }

            SysBoatWater sysBoatWater = SysBoatWater.builder()
                    .boatSn(Const.DEVICE_NET_JG_TOPIC)
                    .taskId(sysTask == null ? 0 : sysTask.getId())
                    .temp(mqtt2NetWqJG.getTemp())
                    .elec(mqtt2NetWqJG.getElec())
                    .PH(mqtt2NetWqJG.getPH())
                    .COD(mqtt2NetWqJG.getCOD())
                    .D0(mqtt2NetWqJG.getD0())
                    .NH4(mqtt2NetWqJG.getNH4())
                    .TS(mqtt2NetWqJG.getTS())
                    .time(DateUtils.getNowDate())
                    .cruiseId(sysTask == null ? 1 : sysTask.getObjectId())
                    .level(level)
                    .longitude(mqtt2NetJG == null ? 0.0 : mqtt2NetJG.getLongitude())
                    .latitude(mqtt2NetJG == null ? 0.0 : mqtt2NetJG.getLatitude())
                    .startTime(DateUtils.getNowDate())
                    .endTime(DateUtils.getNowDate())
                    .build();
            sysBoatWaterMapper.insert(sysBoatWater);
            sendMessage("NetWqJG", sysBoatWater);
        }
    }

    /**
     * 更新电池数据
     */
    public void updateBattery() {
        long temp = (System.currentTimeMillis() - dateStart) / 60000L;
        if (temp > 0) {
            SysBoatBattery sysBoatBattery = SysBoatBattery.builder()
                    .boatSn(Const.DEVICE_NET_JG_TOPIC)
                    .taskId(sysTask == null ? 0 : sysTask.getId())
                    .Thruster_PORT(mqtt2NetPro1JG.getThruster_PORT())
                    .Thruster_STBD(mqtt2NetPro1JG.getThruster_STBD())
                    .Angle_PORT((int) mqtt2NetPro1JG.getAngle_PORT())
                    .Angle_STBD((int) mqtt2NetPro1JG.getAngle_STBD())
                    .status_PORT(mqtt2NetPro1JG.getStatus_PORT())
                    .status_STBD(mqtt2NetPro1JG.getStatus_STBD())
                    .voltage(mqtt2NetPro1JG.getVoltage())
                    .current(mqtt2NetPro1JG.getCurrent())
                    .soc(mqtt2NetPro1JG.getSoc())
                    .cellHVoltage(mqtt2NetPro1JG.getCell_H_Voltage())
                    .cellHvId(mqtt2NetPro1JG.getCell_HV_ID())
                    .cellLVoltage(mqtt2NetPro1JG.getCell_L_Voltage())
                    .cellLvId(mqtt2NetPro1JG.getCell_LV_ID())
                    .cellHTemp(mqtt2NetPro1JG.getCell_H_Temp())
                    .cellHtId(mqtt2NetPro1JG.getCell_HT_ID())
                    .cellLTemp(mqtt2NetPro1JG.getCell_L_Temp())
                    .cellLtId(mqtt2NetPro1JG.getCell_LT_ID())
                    .batteryError(mqtt2NetPro1JG.getBattery_error())
                    .chargeStatus(mqtt2NetPro1JG.getCharge_status())
                    .iResistance(mqtt2NetPro1JG.getI_resistance())
                    .batteryStatus(mqtt2NetPro1JG.getBattery_status())
                    .time(DateUtils.getNowDate())
                    .build();
            sysBoatBatteryMapper.insert(sysBoatBattery);

            //电量小于等于30推送低电量消息
            if (NumberUtil.isLessOrEqual(BigDecimal.valueOf(mqtt2NetPro1JG.getSoc()), BigDecimal.valueOf(30))) {
                sendMessage("NetPro1JPSOC", sysBoatBattery);
            }
        }

    }

    private void checkBoatOnline(Mqtt2NetPro1JG mqtt2NetPro1JG) {
        //如果更新时间为空，则更新数据，否则每隔10秒更新一次数据
        long temp = (System.currentTimeMillis() - boatOnline) / 1000L;
        if (temp > 20 && mqtt2NetPro1JG != null && mqtt2NetPro1JG.getCell_H_Voltage() > 0) {
            boatOnline = System.currentTimeMillis();
            //组合船上线
            onlineBoat();
        }
    }

    /**
     * 解析船发过来的MQTT船体数据
     *
     * @param payload
     */
    public void unPackNetAtJG(String payload) {
        try {
            Mqtt2NetAtJG mqtt2NetAtJG = new Mqtt2NetAtJG();
            List<Mqtt2NetAtJGInfo> mqtt2NetAtJGInfoList = new ArrayList<>();
            String[] parArr = payload.split(",");
            mqtt2NetAtJG.setFrameID(Integer.parseInt(parArr[0]));
            mqtt2NetAtJG.setNum_used_tags(Integer.parseInt(parArr[1]));
            for (int i = 0; i < parArr.length - 2; i++) {
                //解决数组越界
                if (parArr.length - 2 - i < 8) {
                    continue;
                }
                if (i % 8 == 0) {
                    Mqtt2NetAtJGInfo mqtt2NetAtJGInfo = new Mqtt2NetAtJGInfo();
                    mqtt2NetAtJGInfo.setTarget_id(parArr[i + 2]);
//                    mqtt2NetAtJGInfo.setTarget_time(Float.parseFloat(parArr[i + 3]));
                    mqtt2NetAtJGInfo.setTarget_x(Double.parseDouble(parArr[i + 3]));
                    mqtt2NetAtJGInfo.setTarget_y(Double.parseDouble(parArr[i + 4]));
                    Double lng = Double.parseDouble(parArr[i + 5]);
                    Double lat = Double.parseDouble(parArr[i + 6]);
                    //GPS转高德
                    Double[] wgs84ToGcj02 = CoordTransformUtils.wgs84ToGcj02(lng, lat);
                    mqtt2NetAtJGInfo.setTarget_longitude(wgs84ToGcj02[0]);
                    mqtt2NetAtJGInfo.setTarget_latitude(wgs84ToGcj02[1]);
                    mqtt2NetAtJGInfo.setTarget_Ve(Float.parseFloat(parArr[i + 7]));
                    mqtt2NetAtJGInfo.setTarget_Vn(Float.parseFloat(parArr[i + 8]));
                    mqtt2NetAtJGInfo.setTarget_square_radius(Float.parseFloat(parArr[i + 9]));
                    mqtt2NetAtJGInfoList.add(mqtt2NetAtJGInfo);
                }
            }
            mqtt2NetAtJG.setMqtt2NetAtJGInfoList(mqtt2NetAtJGInfoList);
            if (sysTask != null && mqtt2NetAtJG != null) {
                mqtt2NetAtJG.setTaskId(sysTask.getId().intValue());
                mqtt2NetAtJG.setCruiseId(sysTask.getObjectId());
            }
            sendMessage("NetAtJG", mqtt2NetAtJG);
            //TODO 更新正在执行巡河的船的污染区信息sys_boat_pollute表
        } catch (NumberFormatException e) {
            log.error("unPackNetAtJG---:{}", payload, e);
        }
    }

    /**
     * 通知所有在线客户端-用户上线
     */
    public void sendMessage(String module, Object object) {
        try {
            if (messageEventHandler == null) {
                return;
            }
            Set<Map.Entry<String, List<SocketIOClient>>> entrySet = messageEventHandler.getClients().entrySet();
            for (Map.Entry<String, List<SocketIOClient>> entry : entrySet) {
                String key = entry.getKey();
                List<SocketIOClient> value = entry.getValue();
                for (SocketIOClient socketIOClient : value) {
                    //构建推送数据
                    PushBase pushBase = new PushBase();
                    pushBase.setModule(module);
                    pushBase.setContent(object);
                    socketIOClient.sendEvent("newmessage", pushBase);
                }
            }
        } catch (Exception e) {
            log.error("sendMessage", e);
        }
    }

}
